package com.treasure.mall.zbqmallapi.websocket;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;


/**
 * websocket
 * 直播间业务
 */
@Slf4j
@Component
@ServerEndpoint(value = "/websocket/room/{userId}", configurator = WebSocketConfigurator.class)
public class LiveWebSocketServer extends WebSocketBase {

    @Value("${env.debug}")
    private boolean debugMode;

    /**
     * 标识当前连接客户端的用户Id
     */
    private Long userId;
    private String sessionId;

    /**
     * 用于存所有的连接服务的客户端，这个对象存储是安全的
     */
    private static ConcurrentHashMap<String, LiveWebSocketServer> webSocketSet = new ConcurrentHashMap<>();

    private String getUserKey(Long userId, String sessionId) {
        return "wss_" + userId + "_" + sessionId;
    }

    @OnOpen
    public void OnOpen(Session session, @PathParam(value = "userId") Long userId) throws IOException {
        this.session = session;
        this.userId = userId;
        this.sessionId = getRequestParameter("sessionId");
        try {
            //检查是否有效
            if (checkInvalid(userId, sessionId)) {
                session.close(new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE, "参数错误"));
                return;
            }
            // name是用来表示唯一客户端，如果需要指定发送，需要指定发送通过name来区分
            webSocketSet.put(getUserKey(userId, this.sessionId), this);
            if (debugMode) {
                log.info("[WebSocket] userId={} sessionId={} 连接成功，当前连接人数为：={}", this.userId, this.sessionId, webSocketSet.size());
            }
            //进入直播间
            liveSessionService.userEnter(userId, sessionId);
            //更新用户在线总时长
            liveSessionService.updateOnlineTime(userId, sessionId, false);
            //发送加入直播房间消息
            sendJoinRoomMessage(userId, sessionId);

            //检查是否存在直播间消息，并发送
            liveSessionService.sendRoomMessage(sessionId, userId);

            //添加进入直播间的方式
            liveSessionService.addEnterRoomWay(userId, sessionId, getHeader("X-scene", "miniProgram"));


        } catch (Exception e) {
            //检查是否有效
            if (session != null && session.isOpen()) {
                session.close(new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE, "参数错误"));
            }
        }
    }


    @OnClose
    public void OnClose() {
        webSocketSet.remove(getUserKey(userId, this.sessionId));

        //更新用户在线总时长
        liveSessionService.updateOnlineTime(userId, sessionId, true);
        //离开直播间
        liveSessionService.userLeave(userId, sessionId);
        if (debugMode) {
            log.info("[WebSocket] userId={} sessionId={} 退出成功，当前连接人数为：={}", this.userId, this.sessionId, webSocketSet.size());
        }
    }

    @OnMessage
    public void OnMessage(String message, Session session) throws IOException {
        if ("zbq_heartbeat".equals(message)) {
            if (!checkInvalid(userId, sessionId)) {
                liveSessionService.updateOnlineTime(userId, sessionId, false);
            } else {
                if (session != null && session.isOpen()) {
                    session.close(new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE, "参数错误"));
                }
            }
        }
    }

    /**
     * 群发
     *
     * @param message
     */
    public void GroupSending(String message) {
        for (String id : webSocketSet.keySet()) {
            try {
                webSocketSet.get(id).session.getBasicRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 指定发送
     *
     * @param id
     * @param message
     */
    public void AppointSending(String id, String message) {
        try {
            webSocketSet.get(id).session.getBasicRemote().sendText(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
